home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Tool Chest / Development Tools & Languages / Dylan Related / Mindy / Mindy 1.2 - portable sources / comp / parser.y < prev    next >
Encoding:
Text File  |  1995-03-15  |  34.4 KB  |  1,251 lines  |  [TEXT/ttxt]

  1. /**********************************************************************\
  2. *
  3. *  Copyright (c) 1994  Carnegie Mellon University
  4. *  All rights reserved.
  5. *  
  6. *  Use and copying of this software and preparation of derivative
  7. *  works based on this software are permitted, including commercial
  8. *  use, provided that the following conditions are observed:
  9. *  
  10. *  1. This copyright notice must be retained in full on any copies
  11. *     and on appropriate parts of any derivative works.
  12. *  2. Documentation (paper or online) accompanying any system that
  13. *     incorporates this software, or any part of it, must acknowledge
  14. *     the contribution of the Gwydion Project at Carnegie Mellon
  15. *     University.
  16. *  
  17. *  This software is made available "as is".  Neither the authors nor
  18. *  Carnegie Mellon University make any warranty about the software,
  19. *  its performance, or its conformity to any specification.
  20. *  
  21. *  Bug reports, questions, comments, and suggestions should be sent by
  22. *  E-mail to the Internet address "gwydion-bugs@cs.cmu.edu".
  23. *
  24. ***********************************************************************
  25. *
  26. * $Header: parser.y,v 1.15 94/10/05 20:55:49 nkramer Exp $
  27. *
  28. * This file is the grammar.
  29. *
  30. \**********************************************************************/
  31.  
  32. %{
  33. #include "../compat/std-c.h"
  34.  
  35. #include "mindycomp.h"
  36. #include "header.h"
  37. #include "parser.h"
  38. #include "lexer.h"
  39. #include "literal.h"
  40. #include "src.h"
  41. #include "sym.h"
  42.  
  43. struct token_list {
  44.     int token;
  45.     struct token_list *next;
  46. } *yacc_recovery_list = NULL;
  47.  
  48. static void yyerror(char *);
  49. static boolean verify_symbol_aux(struct id *id, struct token *against);
  50. static void yacc_recover();
  51. static void push_yacc_recovery(int token);
  52. static void pop_yacc_recoveries(int count);
  53.  
  54. #define verify_symbol(id,sym) if (verify_symbol_aux(id,sym)) YYERROR
  55.  
  56. %}
  57.  
  58. %union {
  59.     struct _nothing *nothing;
  60.     struct token *token;
  61.     struct body *body;
  62.     struct constituent *constituent;
  63.     struct expr *expr;
  64.     struct bindings *bindings;
  65.     struct param_list *param_list;
  66.     struct param *param;
  67.     struct keyword_param *keyword_param;
  68.     struct id *id;
  69.     struct local_methods *local_methods;
  70.     struct method *method;
  71.     struct binop_series *binop_series;
  72.     struct binop *binop;
  73.     struct literal *literal;
  74.     struct arglist *arglist;
  75.     struct argument *argument;
  76.     struct plist *plist;
  77.     struct return_type_list *return_type_list;
  78.     struct literal_list *literal_list;
  79.     struct block_epilog *block_epilog;
  80.     struct condition_body *condition_body;
  81.     struct incomplete_condition_body *incomplete_condition_body;
  82.     struct condition_clause *condition_clause;
  83.     struct for_header *for_header;
  84.     struct exception_clauses *exception_clauses;
  85.     struct exception_clause *exception_clause;
  86.     struct for_clause *for_clause;
  87.     struct to_part *to_part;
  88.     struct superclass_list *superclass_list;
  89.     struct class_guts *class_guts;
  90.     struct slot_spec *slot_spec;
  91.     struct initarg_spec *initarg_spec;
  92.     boolean bool;
  93.     struct inherited_spec *inherited_spec;
  94.     enum slot_allocation slot_allocation;
  95.     struct gf_suffix *gf_suffix;
  96.     flags_t flags;
  97.     struct else_part *else_part;
  98.  
  99.     struct defnamespace_constituent *defnamespace_constituent;
  100.     struct variable_names *variable_names;
  101.     struct use_clause *use_clause;
  102.     struct use_options *use_options;
  103.     struct use_option *use_option;
  104.     struct import_option *import_option;
  105.     struct renamings *renamings;
  106. }
  107.  
  108. %token <token> HEADER_KEY
  109. %token <token> HEADER_VAL
  110. %token <token> HEADER_END
  111.  
  112. %token <token> BOGUS
  113. %token <token> SYMBOL
  114. %token <token> KEYWORD
  115. %token <token> SYMBOL_LITERAL
  116. %token <token> SHARP_T
  117. %token <token> SHARP_F
  118. %token <token> STRING
  119. %token <token> CHARACTER
  120. %token <token> INTEGER
  121. %token <token> FLOAT
  122. %token <token> BINARY_OPERATOR
  123. %token <token> LPAREN
  124. %token <token> RPAREN
  125. %token <token> COMMA
  126. %token <token> DOT
  127. %token <token> SEMI
  128. %token <token> LBRACKET
  129. %token <token> RBRACKET
  130. %token <token> LBRACE
  131. %token <token> RBRACE
  132. %token <token> COLON_COLON
  133. %token <token> MINUS
  134. %token <token> TILDE
  135. %token <token> EQUAL
  136. %token <token> EQUAL_EQUAL
  137. %token <token> ARROW
  138. %token <token> SHARP_PAREN
  139. %token <token> SHARP_BRACKET
  140. %token <token> NEXT
  141. %token <token> REST
  142. %token <token> KEY
  143. %token <token> ALL_KEYS
  144. %token <token> ABOVE
  145. %token <token> ABSTRACT
  146. %token <token> DBEGIN
  147. %token <token> BELOW
  148. %token <token> BLOCK
  149. %token <token> BY
  150. %token <token> CASE
  151. %token <token> CLASS
  152. %token <token> CLEANUP
  153. %token <token> CONCRETE
  154. %token <token> CONSTANT
  155. %token <token> DEFINE
  156. %token <token> ELSE
  157. %token <token> ELSEIF
  158. %token <token> END
  159. %token <token> EXCEPTION
  160. %token <token> FINALLY
  161. %token <token> FOR
  162. %token <token> FREE
  163. %token <token> FROM
  164. %token <token> GENERIC
  165. %token <token> HANDLER
  166. %token <token> IF
  167. %token <token> IN
  168. %token <token> INHERITED
  169. %token <token> INSTANCE
  170. %token <token> KEYED_BY
  171. %token <token> KEYWORD_RESERVED_WORD
  172. %token <token> LET
  173. %token <token> LOCAL
  174. %token <token> METHOD
  175. %token <token> OPEN
  176. %token <token> OTHERWISE
  177. %token <token> PRIMARY
  178. %token <token> REQUIRED
  179. %token <token> SEAL
  180. %token <token> SEALED
  181. %token <token> SELECT
  182. %token <token> SLOT
  183. %token <token> SUBCLASS
  184. %token <token> THEN
  185. %token <token> TO
  186. %token <token> UNLESS
  187. %token <token> UNTIL
  188. %token <token> VARIABLE
  189. %token <token> VIRTUAL
  190. %token <token> WHILE
  191.  
  192. %token <token> MODULE
  193. %token <token> LIBRARY
  194. %token <token> EXPORT
  195. %token <token> CREATE
  196. %token <token> USE
  197. %token <token> ALL
  198.  
  199. /* These tokens sometimes have special significance and are sometimes just
  200.    keywords */
  201. %token <token> PREFIX_OPTION
  202. %token <token> IMPORT_OPTION
  203. %token <token> EXCLUDE_OPTION
  204. %token <token> EXPORT_OPTION
  205. %token <token> RENAME_OPTION
  206. %type  <token> keyword keyword_opt
  207.  
  208. %type <nothing> dylan_file dylan_headers header_list
  209. %type <nothing> dylan_program block_opt case_opt if_opt for_opt select_opt
  210. %type <nothing> unless_opt until_opt while_opt class_opt method_opt semi_opt
  211. %type <nothing> arrow_opt
  212. %type <token> symbol_opt
  213. %type <body> body body_opt constituents cleanup_part
  214. %type <body> final_part final_part_opt
  215. %type <constituent> constituent defining_form local_declaration
  216. %type <constituent> class_definition generic_function_definition
  217. %type <bindings> bindings
  218. %type <param_list> variables gf_parameters
  219. %type <param_list> more_gf_parameters gf_rest_parameters
  220. %type <param_list> gf_keyword_parameters_list gf_keyword_parameters_opt
  221. %type <param_list> gf_keyword_parameters parameters more_parameters
  222. %type <param_list> next_parameters rest_parameters keyword_parameters_list
  223. %type <param_list> keyword_parameters_opt keyword_parameters
  224. %type <param> variable positional_parameter
  225. %type <keyword_param> keyword_parameter gf_keyword_parameter
  226. %type <id> next_parameter rest_parameter
  227. %type <local_methods> local_methods
  228. %type <method> local_method anonymous_method named_method method_description
  229. %type <expr> expression operand leaf statement by_part by_part_opt 
  230. %type <expr> slot_type_opt return_type_element keyword_parameter_type
  231. %type <expr> keyword_parameter_default
  232. %type <binop_series> binop_series
  233. %type <binop> binop
  234. %type <arglist> arguments_opt arguments
  235. %type <argument> argument
  236. %type <plist> property_list_opt property_list
  237. %type <return_type_list> return_type return_type_list return_type_list_head
  238. %type <literal> constant concat_string literal dotted_list
  239. %type <literal_list> literals_opt literals
  240. %type <block_epilog> block_epilog block_epilog_opt
  241. %type <condition_body> condition_body complete_condition_clauses
  242. %type <for_header> for_header
  243. %type <exception_clauses> exception_clauses_opt exception_clauses
  244. %type <exception_clause> exception_clause
  245. %type <incomplete_condition_body> incomplete_condition_clauses
  246. %type <condition_clause> condition_clause
  247. %type <for_clause> for_clause
  248. %type <to_part> to_part_opt
  249. %type <superclass_list> superclasses
  250. %type <class_guts> class_guts_opt class_guts
  251. %type <slot_spec> slot_spec
  252. %type <initarg_spec> initarg_spec
  253. %type <bool> required_opt
  254. %type <inherited_spec> inherited_spec
  255. %type <slot_allocation> allocation
  256. %type <gf_suffix> gf_suffix
  257. %type <flags> flags 
  258. %type <else_part> else_part else_part_opt
  259.  
  260. %type <constituent> module_definition library_definition 
  261. %type <defnamespace_constituent> module_clauses_opt module_clauses
  262. %type <defnamespace_constituent> library_clauses_opt library_clauses
  263. %type <nothing> module_opt library_opt
  264. %type <variable_names> export_clause create_clause 
  265. %type <use_clause> use_clause 
  266. %type <use_options> module_use_options 
  267. %type <use_option> module_use_option prefix_option exclude_option
  268. %type <use_option> rename_option export_option import_option
  269. %type <renamings> rename_specs
  270. %type <import_option> imports imports_opt
  271. %type <variable_names> variable_name_set variable_names
  272.  
  273. %%
  274.  
  275. dylan_file:
  276.     dylan_headers dylan_program
  277. ;
  278.  
  279. dylan_headers:
  280.     HEADER_END    { process_header(NULL, NULL); free($1); }
  281.     |    header_list HEADER_END    { process_header(NULL, NULL); free($2); }
  282. ;
  283.  
  284. header_list:
  285.     HEADER_KEY HEADER_VAL
  286.     { process_header((char *)$1->chars, (char *)$2->chars); free($1); free($2); }
  287.     |    header_list HEADER_KEY HEADER_VAL
  288.     { process_header((char *)$2->chars, (char *)$3->chars); free($2); free($3); }
  289. ;
  290.  
  291. dylan_program:
  292.     { push_yacc_recovery(SEMI); }
  293.     body    { Program = $2; $$ = NULL; }
  294. ;
  295.  
  296. body:
  297.     constituents semi_opt    { $$ = $1; }
  298. ;
  299.  
  300. body_opt:
  301.     /* epsilon */    { $$ = make_body(); }
  302.     |    body        { $$ = $1; }
  303. ;
  304.  
  305.  
  306. constituents:
  307.     constituent
  308.     { $$ = add_constituent(make_body(), $1); }
  309.     |    constituents SEMI constituent
  310.     { free($2); $$ = add_constituent($1, $3); }
  311. ;
  312.  
  313. constituent:
  314.     defining_form        { $$ = $1; }
  315.     |    local_declaration    { $$ = $1; }
  316.     |    expression        { $$ = make_expr_constituent($1); }
  317.     |   error            { $$ = make_error_constituent(); }
  318. ;
  319.  
  320. defining_form:
  321.     DEFINE flags CLASS class_definition
  322.     { free($1); free($3); $$ = set_class_flags($2, $4); }
  323.     |    DEFINE CONSTANT bindings
  324.     { free($1); $$ = make_define_constant($2->line, $3); free($2); }
  325.     |    DEFINE flags GENERIC generic_function_definition
  326.     { free($1); free($3); $$ = set_generic_flags($2, $4); }
  327.     |    DEFINE flags METHOD named_method
  328.     { free($1); free($3); $$ = make_define_method($2, $4); }
  329.     |    DEFINE VARIABLE bindings
  330.     { free($1); $$ = make_define_variable($2->line, $3); free($2); }
  331.     |    DEFINE MODULE module_definition
  332.     { free($1); free($2); $$ = $3; }
  333.     |    DEFINE LIBRARY library_definition
  334.     { free($1); free($2); $$ = $3; }
  335. ;
  336.  
  337. flags:
  338.     /* epsilon */ { $$ = 0; }
  339.     |    flags SEALED { free($2); $$ = $1 | flag_SEALED; }
  340.     |    flags OPEN { free($2); $$ = $1 | flag_OPEN; }
  341.     |    flags ABSTRACT { free($2); $$ = $1 | flag_ABSTRACT; }
  342.     |    flags CONCRETE { free($2); $$ = $1 | flag_CONCRETE; }
  343.     |    flags PRIMARY { free($2); $$ = $1 | flag_PRIMARY; }
  344.     |    flags FREE { free($2); $$ = $1 | flag_FREE; }
  345. ;    
  346.  
  347. local_declaration:
  348.     LET bindings
  349.     { free($1); $$ = make_let($2); }
  350.     |    LET HANDLER SYMBOL EQUAL expression
  351.     { free($1); free($2); free($4);
  352.       $$ = make_handler(make_varref(make_id($3)), $5, NULL);
  353.     }
  354.     |    LET HANDLER LPAREN expression property_list_opt RPAREN EQUAL expression
  355.     { free($1); free($2); free($3); free($6); free($7);
  356.       $$ = make_handler($4, $8, $5);
  357.     }
  358.     |    LOCAL local_methods
  359.     { free($1); $$ = make_local_constituent($2); }
  360. ;
  361.  
  362. bindings:
  363.     variable EQUAL expression
  364.     { free($2); $$ = make_bindings(push_param($1,make_param_list()), $3); }
  365.     |    LPAREN variables RPAREN EQUAL expression
  366.     { free($1); free($3); free($4); $$ = make_bindings($2, $5); }
  367. ;
  368.  
  369. variables:
  370.     rest_parameter
  371.     { $$ = set_rest_param(make_param_list(), $1); }
  372.     |    variable
  373.     { $$ = push_param($1, make_param_list()); }
  374.     |    variable COMMA variables
  375.     { free($2); $$ = push_param($1, $3); }
  376. ;
  377.  
  378. variable:
  379.     SYMBOL { $$ = make_param(make_id($1), NULL); }
  380.     |    SYMBOL COLON_COLON operand
  381.     { free($2); $$ = make_param(make_id($1), $3); }
  382. ;
  383.  
  384. local_methods:
  385.     local_method { $$ = add_local_method(make_local_methods(), $1); }
  386.     |    local_methods COMMA local_method
  387.     { free($2); $$ = add_local_method($1, $3); }
  388. ;
  389.  
  390. local_method:
  391.     method_opt named_method { $$ = $2; }
  392. ;
  393.  
  394. keyword:
  395.     KEYWORD
  396.     |    PREFIX_OPTION
  397.     |    IMPORT_OPTION
  398.     |    EXCLUDE_OPTION
  399.     |    EXPORT_OPTION
  400.     |    RENAME_OPTION
  401. ;
  402.  
  403. expression:
  404.     keyword { $$ = make_literal_ref(parse_keyword_token($1)); }
  405.     |    operand { $$ = $1; }
  406.     |    operand binop_series
  407.     { $$ = make_binop_series_expr($1, $2); }
  408. ;
  409.  
  410. binop_series:
  411.     binop operand { $$ = add_binop(make_binop_series(), $1, $2); }
  412.     |    binop_series binop operand { $$ = add_binop($1, $2, $3); }
  413. ;
  414.  
  415. binop:
  416.     BINARY_OPERATOR { $$ = make_binop(make_id($1)); }
  417.     |    MINUS { $$ = make_binop(make_id($1)); }
  418.     |    EQUAL { $$ = make_binop(make_id($1)); }
  419.     |    EQUAL_EQUAL { $$ = make_binop(make_id($1)); }
  420. ;
  421.  
  422. operand:
  423.     MINUS operand { free($1); $$ = make_negate($2); }
  424.     |    TILDE operand { free($1); $$ = make_not($2); }
  425.     |    leaf { $$ = $1; }
  426. ;
  427.  
  428. leaf:
  429.     constant { $$ = make_literal_ref($1); }
  430.     |    SYMBOL { $$ = make_varref(make_id($1)); }
  431.     |    leaf LBRACKET arguments_opt RBRACKET
  432.     { free($2); free($4); $$ = make_aref_or_element($1, $3); }
  433.     |    leaf LPAREN arguments_opt RPAREN
  434.     { free($2); free($4); $$ = make_function_call($1, $3); }
  435.     |    anonymous_method { $$ = make_method_ref($1); }
  436.     |    leaf DOT SYMBOL
  437.     { free($2);
  438.       $$ = make_dot_operation($1, make_varref(make_id($3)));
  439.     }
  440.     |    LPAREN expression RPAREN { $$ = $2; free($1); free($3); }
  441.     |    statement { $$ = $1; }
  442. ;
  443.  
  444. arguments_opt:
  445.     /* epsilon */ { $$ = make_argument_list(); }
  446.     |    arguments { $$ = $1; }
  447. ;
  448.  
  449. arguments:
  450.     argument { $$ = add_argument(make_argument_list(), $1); }
  451.     |    arguments COMMA argument { free($2); $$ = add_argument($1, $3); }
  452. ;
  453.  
  454. argument:
  455.     expression { $$ = make_argument($1); }
  456.     |    keyword expression
  457.     { $$ = make_keyword_argument($1, $2); }
  458. ;
  459.  
  460. constant:
  461.     SHARP_T { $$ = parse_true_token($1); }
  462.     |    SHARP_F { $$ = parse_false_token($1); }
  463.     |    concat_string { $$ = $1; }
  464.     |    CHARACTER { $$ = parse_character_token($1); }
  465.     |    INTEGER { $$ = parse_integer_token($1); }
  466.     |    FLOAT { $$ = parse_float_token($1); }
  467.     |    SYMBOL_LITERAL { $$ = parse_keyword_token($1); }
  468.     |    SHARP_PAREN dotted_list RPAREN
  469.     { free($1); free($3); $$ = $2; }
  470.     |    SHARP_PAREN literals_opt RPAREN
  471.     { free($1); free($3); $$ = make_list_literal($2); }
  472.     |    SHARP_BRACKET literals_opt RBRACKET
  473.     { free($1); free($3); $$ = make_vector_literal($2); }
  474. ;
  475.  
  476. concat_string:
  477.     STRING             { $$ = parse_string_token($1); }
  478.     |    concat_string STRING    { $$ = concat_string_token($1, $2); }
  479.  
  480. dotted_list:
  481.     literals DOT literal
  482.     { free($2); $$ = make_dotted_list_literal($1, $3); }
  483. ;
  484.  
  485. literals_opt:
  486.     /* epsilon */
  487.     { $$ = make_literal_list(); }
  488.     |    literals
  489.     { $$ = $1; }
  490. ;
  491.  
  492. literals:
  493.     literal { $$ = add_literal(make_literal_list(), $1); }
  494.     |    literals COMMA literal
  495.     { free($2); $$ = add_literal($1, $3); }
  496. ;
  497.  
  498. literal:
  499.     constant { $$ = $1; }
  500.     |    keyword { $$ = parse_keyword_token($1); }
  501. ;
  502.  
  503. statement:
  504.     DBEGIN { push_yacc_recovery(END); }
  505.     body_opt END
  506.     { free($1); free($4); $$ = make_body_expr($3);
  507.           pop_yacc_recoveries(1); }
  508.     |    BLOCK LPAREN symbol_opt RPAREN { push_yacc_recovery(END);
  509.                      push_yacc_recovery(CLEANUP);
  510.                      push_yacc_recovery(EXCEPTION); }
  511.     body block_epilog_opt END block_opt
  512.     { free($2); free($4); free($8); pop_yacc_recoveries(3); 
  513.       $$ = make_block($1->line, $3 ? make_id($3) : NULL, $6, $7);
  514.       free($1);
  515.     }
  516.     |    CASE { push_yacc_recovery(END); }
  517.     condition_body END case_opt
  518.     { free($1); free($4); $$ = make_case($3);
  519.           pop_yacc_recoveries(1); }
  520.     |    IF LPAREN expression RPAREN { push_yacc_recovery(END);
  521.                       push_yacc_recovery(ELSE); }
  522.     body else_part_opt END if_opt
  523.     { free($1); free($2); free($4); free($8); $$ = make_if($3, $6, $7);
  524.           pop_yacc_recoveries(2); }
  525.     |    FOR LPAREN for_header RPAREN { push_yacc_recovery(END);
  526.                        push_yacc_recovery(FINALLY); }
  527.     body_opt final_part_opt END for_opt
  528.     { free($1); free($2); free($4); free($8); $$ = make_for($3, $6, $7);
  529.           pop_yacc_recoveries(2); }
  530.     |    SELECT LPAREN expression by_part_opt RPAREN {push_yacc_recovery(END);}
  531.         condition_body END select_opt
  532.     { free($1);free($2);free($5);free($8); $$ = make_select($3, $4, $7);
  533.           pop_yacc_recoveries(1); }
  534.     |    UNLESS LPAREN expression RPAREN { push_yacc_recovery(END); }
  535.     body END unless_opt
  536.     { free($1);free($2);free($4);free($7);
  537.       $$ = make_if($3, NULL, make_else(0, $6));
  538.           pop_yacc_recoveries(1); }
  539.     |    UNTIL LPAREN expression RPAREN { push_yacc_recovery(END); }
  540.         body_opt END until_opt
  541.     { free($1);free($2);free($4);free($7); pop_yacc_recoveries(1);
  542.       $$ = make_for(make_for_header($3), $6, NULL);
  543.     }
  544.     |    WHILE LPAREN expression RPAREN { push_yacc_recovery(END); }
  545.     body_opt END while_opt
  546.     { free($1);free($2);free($4);free($7);pop_yacc_recoveries(1);
  547.       $$ = make_for(make_for_header(make_not($3)), $6, NULL);
  548.     }
  549. ;
  550.  
  551. block_epilog_opt:
  552.     /* epsilon */ { $$ = NULL; }
  553.     |    block_epilog { $$ = $1; }
  554. ;
  555.  
  556. block_epilog:
  557.     exception_clauses_opt cleanup_part exception_clauses_opt
  558.     { $$ = make_block_epilog($1, $2, $3); }
  559.     |    exception_clauses
  560.     { $$ = make_block_epilog($1, NULL, NULL); }
  561. ;
  562.  
  563. condition_body:
  564.     complete_condition_clauses { $$ = $1; }
  565. ;
  566.  
  567. for_header:
  568.     UNTIL expression
  569.     { free($1); $$ = make_for_header($2); }
  570.     |    WHILE expression
  571.     { free($1); $$ = make_for_header(make_not($2)); }
  572.     |    for_clause
  573.     { $$ = push_for_clause($1, make_for_header(NULL)); }
  574.     |    for_clause COMMA for_header
  575.     { free($2); $$ = push_for_clause($1, $3); }
  576. ;
  577.  
  578. exception_clauses_opt:
  579.     /* epsilon */ { $$ = NULL; }
  580.     |    exception_clauses { $$ = $1; }
  581. ;
  582.  
  583. exception_clauses:
  584.     exception_clause
  585.     { $$ = add_exception_clause(make_exception_clauses(), $1); }
  586.     |    exception_clauses exception_clause
  587.     { $$ = add_exception_clause($1, $2); }
  588. ;
  589.  
  590. exception_clause:
  591.     EXCEPTION SYMBOL body
  592.     { free($1);
  593.       $$ = make_exception_clause(make_varref(make_id($2)),
  594.                      NULL, NULL, $3);
  595.     }
  596.     |    EXCEPTION LPAREN expression property_list_opt RPAREN body
  597.     { free($1); free($2); free($5);
  598.       $$ = make_exception_clause($3, NULL, $4, $6);
  599.     }
  600.     |    EXCEPTION LPAREN SYMBOL COLON_COLON expression property_list_opt RPAREN
  601.         body
  602.     { free($1); free($2); free($4); free($7);
  603.       $$ = make_exception_clause($5, make_id($3), $6, $8);
  604.     }
  605. ;
  606.  
  607. complete_condition_clauses:
  608.     OTHERWISE arrow_opt body
  609.     { free($1);
  610.       $$ = push_condition_clause(make_otherwise_condition_clause($3),
  611.                      NULL);
  612.     }
  613.     |    condition_clause semi_opt
  614.     { $$ = push_condition_clause($1, NULL); }
  615.     |    condition_clause SEMI complete_condition_clauses
  616.     { free($2); $$ = push_condition_clause($1, $3); }
  617.     |    condition_clause SEMI incomplete_condition_clauses
  618.     { free($2); $$ = complete_condition_clauses($1, $3); }
  619. ;
  620.  
  621. incomplete_condition_clauses:
  622.     constituent semi_opt
  623.     { $$ = make_incomplete_condition_clauses($1, NULL); }
  624.     |    constituent SEMI complete_condition_clauses
  625.     { free($2); $$ = make_incomplete_condition_clauses($1, $3); }
  626.     |    constituent SEMI incomplete_condition_clauses
  627.     { free($2); $$ = push_condition_constituent($1, $3); }
  628. ;
  629.  
  630. condition_clause:
  631.     expression ARROW constituent
  632.     { free($2); $$ = push_condition($1, make_condition_clause($3)); }
  633.     |    expression COMMA condition_clause
  634.     { free($2); $$ = push_condition($1, $3); }
  635. ;
  636.  
  637. for_clause:
  638.     variable EQUAL expression THEN expression
  639.     { free($2); free($4);
  640.     $$=make_equal_then_for_clause(push_param($1,make_param_list()),$3,$5);}
  641.     |    LPAREN variables RPAREN EQUAL expression THEN expression
  642.     { free($1); free($3); free($4); free($6);
  643.       $$ = make_equal_then_for_clause($2, $5, $7); }
  644.     |    variable IN expression 
  645.     { free($2); $$ = make_in_for_clause($1, NULL, $3); }
  646.     |    variable KEYED_BY variable IN expression
  647.     { free($2); free($4); $$ = make_in_for_clause($1, $3, $5); }
  648.     |    variable FROM expression to_part_opt by_part_opt
  649.     { free($2); $$ = make_from_for_clause($1, $3, $4, $5); }
  650. ;
  651.  
  652. by_part:    BY expression { free($1); $$ = $2; } ;
  653. cleanup_part:    CLEANUP body { free($1); $$ = $2; } ;
  654. final_part:    FINALLY body { free($1); $$ = $2; } ;
  655.  
  656. else_part:
  657.     ELSE body { $$ = make_else($1->line, $2); free($1); }
  658.     |    ELSEIF LPAREN expression RPAREN body else_part_opt
  659.     { free($2); free($4);
  660.       $$ = make_else($1->line, make_expr_body(make_if($3, $5, $6)));
  661.       free($1); 
  662.     }
  663. ;
  664.  
  665. to_part_opt:
  666.     /* epsilon */ { $$ = NULL; }
  667.     |    TO expression { free($1); $$ = make_to($2); }
  668.     |    ABOVE expression { free($1); $$ = make_above($2); }
  669.     |    BELOW expression { free($1); $$ = make_below($2); }
  670. ;
  671.  
  672. class_definition:
  673.     SYMBOL LPAREN superclasses RPAREN
  674.         class_guts_opt END class_opt symbol_opt
  675.     { struct id *id = make_id($1);
  676.       verify_symbol(id, $8); free($2); free($4); free($6);
  677.       $$ = make_class_definition(id, $3, $5);
  678.     }
  679. ;
  680.  
  681. superclasses:
  682.     expression
  683.     { $$ = add_superclass(make_superclass_list(), $1); }
  684.     |    superclasses COMMA expression
  685.     { free($2); $$ = add_superclass($1, $3); }
  686. ;
  687.  
  688. class_guts_opt:
  689.     /* epsilon */ { $$ = NULL; }
  690.     |    class_guts semi_opt { $$ = $1; }
  691. ;
  692.  
  693. class_guts:
  694.     slot_spec
  695.     { $$ = add_slot_spec(make_class_guts(), $1); }
  696.     |    initarg_spec
  697.     { $$ = add_initarg_spec(make_class_guts(), $1); }
  698.     |    inherited_spec
  699.     { $$ = add_inherited_spec(make_class_guts(), $1); }
  700.     |    class_guts SEMI slot_spec
  701.     { free($2); $$ = add_slot_spec($1, $3); }
  702.     |    class_guts SEMI initarg_spec
  703.     { free($2); $$ = add_initarg_spec($1, $3); }
  704.     |    class_guts SEMI inherited_spec
  705.     { free($2); $$ = add_inherited_spec($1, $3); }
  706. ;
  707.  
  708. slot_spec:
  709.     flags allocation SLOT SYMBOL slot_type_opt property_list_opt
  710.     {
  711.         int line = $3->line;
  712.         free($3);
  713.         $$ = make_slot_spec(line, $1, $2, $4 ? make_id($4) : NULL, $5, $6);
  714.     }
  715. ;
  716.  
  717. initarg_spec:
  718.     required_opt KEYWORD_RESERVED_WORD KEYWORD property_list_opt
  719.     { free($2); $$ = make_initarg_spec($1, $3, $4); }
  720. ;
  721.  
  722. required_opt:
  723.     REQUIRED { free($1); $$ = TRUE; }
  724.     |    /* epsilon */ { $$ = FALSE; }
  725. ;
  726.  
  727. inherited_spec:
  728.     INHERITED SLOT SYMBOL property_list_opt
  729.     { free($1); free($2); $$ = make_inherited_spec(make_id($3), $4); }
  730. ;
  731.  
  732.  
  733. allocation:
  734.     /* epsilon */ { $$ = alloc_INSTANCE; }
  735.     |    INSTANCE { free($1); $$ = alloc_INSTANCE; }
  736.     |    CLASS { free($1); $$ = alloc_CLASS; }
  737.     |    SUBCLASS { free($1); $$ = alloc_SUBCLASS; }
  738.     |    CONSTANT { free($1); $$ = alloc_CONSTANT; }
  739.     |    VIRTUAL { free($1); $$ = alloc_VIRTUAL; }
  740. ;
  741.  
  742. slot_type_opt:
  743.     /* epsilon */ { $$ = NULL; }
  744.     |    COLON_COLON expression { free($1); $$ = $2; }
  745. ;
  746.  
  747. property_list_opt:
  748.     /* epsilon */ { $$ = make_property_list(); }
  749.     |    property_list { $$ = $1; }
  750. ;
  751.  
  752. property_list:
  753.     COMMA keyword expression
  754.     { free($1); $$ = add_property(make_property_list(), $2, $3); }
  755.     |    property_list COMMA keyword expression
  756.     { free($2); $$ = add_property($1, $3, $4); }
  757. ;
  758.  
  759. generic_function_definition:
  760.     SYMBOL LPAREN gf_parameters RPAREN gf_suffix
  761.     { free($2); free($4);
  762.       $$ = make_define_generic(make_id($1), $3, $5);
  763.     }
  764. ;
  765.  
  766. gf_suffix:
  767.     property_list_opt
  768.     { $$ = make_gf_suffix(NULL, $1); }
  769.     |    ARROW return_type_element property_list_opt
  770.     { free($1);
  771.       $$ = make_gf_suffix
  772.               (add_return_type(make_return_type_list(FALSE, NULL), $2),
  773.            $3);
  774.     }
  775.     |    ARROW LPAREN return_type_list RPAREN property_list_opt
  776.     { free($1); free($2); free($4); $$ = make_gf_suffix($3, $5); }
  777. ;
  778.  
  779. gf_parameters:
  780.     /* epsilon */ { $$ = make_param_list(); }
  781.     |    positional_parameter more_gf_parameters
  782.     { $$ = push_param($1, $2); }
  783.     |    gf_rest_parameters { $$ = $1; }
  784. ;
  785.  
  786. more_gf_parameters:
  787.     /* epsilon */
  788.     { $$ = make_param_list(); }
  789.     |    COMMA positional_parameter more_gf_parameters
  790.     { free($1); $$ = push_param($2, $3); }
  791.     |    COMMA gf_rest_parameters
  792.     { free($1); $$ = $2; }
  793. ;
  794.  
  795. gf_rest_parameters:
  796.     rest_parameter
  797.     { $$ = set_rest_param(make_param_list(), $1); }
  798.     |    rest_parameter COMMA gf_keyword_parameters_list
  799.     { free($2); $$ = set_rest_param($3, $1); }
  800.     |    gf_keyword_parameters_list
  801.     { $$ = $1; }
  802. ;
  803.  
  804. gf_keyword_parameters_list:
  805.     KEY gf_keyword_parameters_opt { free($1); $$ = $2; }
  806.     |    ALL_KEYS { free($1); $$ = allow_all_keywords(make_param_list()); }
  807. ;
  808.  
  809. gf_keyword_parameters_opt:
  810.     /* epsilon */ { $$ = allow_keywords(make_param_list()); }
  811.     |    gf_keyword_parameters { $$ = $1; }
  812. ;
  813.  
  814. gf_keyword_parameters:
  815.     gf_keyword_parameter
  816.     { $$ = push_keyword_param($1, allow_keywords(make_param_list())); }
  817.     |    gf_keyword_parameter COMMA ALL_KEYS
  818.     { free($2); free($3);
  819.       $$ = push_keyword_param($1, allow_all_keywords(make_param_list())); }
  820.     |    gf_keyword_parameter COMMA gf_keyword_parameters
  821.     { free($2); $$ = push_keyword_param($1, $3); }
  822. ;
  823.  
  824. gf_keyword_parameter:
  825.     keyword symbol_opt keyword_parameter_type
  826.     { $$ = make_keyword_param($1, $2 ? make_id($2) : NULL, $3, NULL); }
  827.     |    SYMBOL keyword_parameter_type
  828.     { $$ = make_keyword_param(NULL, make_id($1), $2, NULL); }
  829. ;
  830.  
  831. anonymous_method:
  832.     METHOD method_description END method_opt
  833.     { free($3); $$ = set_method_source($1, $2); }
  834. ;
  835.  
  836. named_method:
  837.     SYMBOL method_description END method_opt symbol_opt
  838.     { struct id *id = make_id($1);
  839.       free($3); verify_symbol(id, $5);
  840.       $$ = set_method_name(id, $2);
  841.     }
  842. ;
  843.  
  844. method_description:
  845.     LPAREN parameters RPAREN return_type SEMI body
  846.     { free($1); free($3); free($5);
  847.       $$ = make_method_description($2, $4, $6);
  848.     }
  849.     |    LPAREN parameters RPAREN return_type semi_opt
  850.     { free($1); free($3);
  851.       $$ = make_method_description($2, $4, make_body());
  852.     }
  853.     |    LPAREN parameters RPAREN semi_opt body_opt
  854.     { free($1); free($3);
  855.       $$ = make_method_description($2, NULL, $5);
  856.     }
  857. ;
  858.  
  859. return_type:
  860.     ARROW return_type_list
  861.     { free($1); $$ = $2; }
  862.     |    ARROW LPAREN return_type_list RPAREN
  863.     { free($1); free($2); free($4); $$ = $3; }
  864. ;
  865.  
  866. return_type_list:
  867.     /* epsilon */
  868.     { $$ = make_return_type_list(FALSE, NULL); }
  869.     |    REST return_type_element
  870.     { free($1); $$ = make_return_type_list(TRUE, $2); }
  871.     |    return_type_list_head
  872.     { $$ = $1; }
  873.     |    return_type_list_head COMMA REST return_type_element
  874.     { free($2); free($3); $$ = set_return_type_rest_type($1, $4); }
  875. ;
  876.  
  877. return_type_list_head:
  878.     return_type_element
  879.     { $$ = add_return_type(make_return_type_list(FALSE, NULL), $1); }
  880.     |    return_type_list_head COMMA return_type_element
  881.     { free($2); $$ = add_return_type($1, $3); }
  882. ;
  883.  
  884. return_type_element:
  885.     SYMBOL { free($1); $$ = NULL; }
  886.     |    SYMBOL COLON_COLON expression { free($1); free($2); $$ = $3; }
  887. ;
  888.  
  889. parameters:
  890.     /* epsilon */ { $$ = make_param_list(); }
  891.     |    positional_parameter more_parameters { $$ = push_param($1, $2); }
  892.     |    next_parameters { $$ = $1; }
  893. ;
  894.  
  895. more_parameters:
  896.     /* epsilon */
  897.     { $$ = make_param_list(); }
  898.     |    COMMA positional_parameter more_parameters
  899.     { free($1); $$ = push_param($2, $3); }
  900.     |    COMMA next_parameters
  901.     { free($1); $$ = $2; }
  902. ;
  903.  
  904. positional_parameter:
  905.     SYMBOL
  906.     { $$ = make_param(make_id($1), NULL); }
  907.     |    SYMBOL COLON_COLON expression
  908.     { free($2); $$ = make_param(make_id($1), $3); }
  909.     |    SYMBOL EQUAL_EQUAL expression
  910.     { free($2); $$ = make_param(make_id($1), make_singleton($3)); }
  911. ;
  912.  
  913. next_parameters:
  914.     next_parameter
  915.     { $$ = set_next_param(make_param_list(), $1); }
  916.     |    next_parameter COMMA rest_parameters
  917.     { free($2); $$ = set_next_param($3, $1); }
  918.     |    rest_parameters
  919.     { $$ = $1; }
  920. ;
  921.  
  922. next_parameter:
  923.     NEXT SYMBOL { free($1); $$ = make_id($2); }
  924. ;
  925.  
  926. rest_parameters:
  927.     rest_parameter
  928.     { $$ = set_rest_param(make_param_list(), $1); }
  929.     |    rest_parameter COMMA keyword_parameters_list
  930.     { free($2); $$ = set_rest_param($3, $1); }
  931.     |    keyword_parameters_list
  932.     { $$ = $1; }
  933. ;
  934.  
  935. rest_parameter:
  936.     REST SYMBOL { free($1); $$ = make_id($2); }
  937. ;
  938.  
  939. keyword_parameters_list:
  940.     KEY keyword_parameters_opt
  941.     { free($1); $$ = $2; }
  942.     |    ALL_KEYS
  943.     { free($1); $$ = allow_all_keywords(make_param_list()); }
  944. ;
  945.  
  946. keyword_parameters_opt:
  947.     /* epsilon */ { $$ = allow_keywords(make_param_list()); }
  948.     |    COMMA ALL_KEYS
  949.     { free($1); free($2); $$ = allow_all_keywords(make_param_list()); }
  950.     |    keyword_parameters { $$ = $1; }
  951. ;
  952.  
  953. keyword_parameters:
  954.     keyword_parameter
  955.     { $$ = push_keyword_param($1, allow_keywords(make_param_list())); }
  956.     |    keyword_parameter COMMA ALL_KEYS
  957.     { free($2); free($3);
  958.       $$ = push_keyword_param($1, allow_all_keywords(make_param_list())); }
  959.     |    keyword_parameter COMMA keyword_parameters
  960.     { free($2); $$ = push_keyword_param($1, $3); }
  961. ;
  962.  
  963. keyword_parameter:
  964.     keyword_opt SYMBOL keyword_parameter_type keyword_parameter_default
  965.     { $$ = make_keyword_param($1, make_id($2), $3, $4); }
  966.     |    keyword_opt SYMBOL LPAREN expression RPAREN
  967.     { free($3); free($5);
  968.       $$ = make_keyword_param($1, make_id($2), NULL, $4); }
  969. ;
  970.  
  971. keyword_opt:
  972.     /* epsilon */ { $$ = NULL; }
  973.     |    keyword { $$ = $1; }
  974. ;    
  975.  
  976. keyword_parameter_type:
  977.     /* epsilon */ { $$ = NULL; }
  978.     |    COLON_COLON operand { free($1); $$ = $2; }
  979. ;
  980.  
  981. keyword_parameter_default:
  982.     /* epsilon */ { $$ = NULL; }
  983.     |    EQUAL expression { free($1); $$ = $2; }
  984. ;
  985.  
  986. module_definition:
  987.     SYMBOL module_clauses_opt END module_opt symbol_opt
  988.     { if ($5) {
  989.           if (strcasecmp((char *)$1->chars, (char *)$5->chars) != 0) {
  990.           error($5->line, "mismatched name, ``%s'' isn't ``%s''",
  991.             $5->chars, $1->chars);
  992.           yacc_recover();
  993.           }
  994.           free($5);
  995.       } 
  996.       free($3);
  997.       $$ = (struct constituent *) set_namespace_name($2, $1);
  998.     }
  999. ;
  1000.  
  1001. module_opt:
  1002.     /* empty */         { $$ = NULL; }
  1003.     |    MODULE            { free($1); $$ = NULL; }
  1004.  
  1005. module_clauses_opt:
  1006.     /* empty */        { $$ = make_define_module(); }
  1007.     |    module_clauses
  1008.     |    module_clauses SEMI    { $$ = $1; free($2); }
  1009. ;
  1010.  
  1011. module_clauses:
  1012.     use_clause
  1013.     { $$ = add_use_clause(make_define_module(), $1); }
  1014.     |    export_clause
  1015.     { $$ = add_exports(make_define_module(), $1); }
  1016.     |    create_clause
  1017.     { $$ = add_creates(make_define_module(), $1); }
  1018.     |    module_clauses SEMI use_clause
  1019.     { $$ = add_use_clause($1, $3); free($2); }
  1020.     |    module_clauses SEMI export_clause
  1021.     { $$ = add_exports($1, $3); free($2); }
  1022.     |    module_clauses SEMI create_clause
  1023.     { $$ = add_creates($1, $3); free($2); }
  1024. ;
  1025.  
  1026. export_clause:
  1027.     EXPORT variable_names    { free($1); $$ = $2; }
  1028. ;
  1029.  
  1030. create_clause:
  1031.     CREATE variable_names    { free($1); $$ = $2; }
  1032. ;
  1033.  
  1034. use_clause:
  1035.     USE SYMBOL module_use_options
  1036.     { free($1); $$ = make_use_clause($2, $3); }
  1037. ;
  1038.  
  1039. module_use_options:
  1040.     /* empty */        { $$ = make_use_options(); }
  1041.     |    module_use_options COMMA module_use_option
  1042.     { free($2); $$ = add_use_option($1, $3); }
  1043. ;
  1044.  
  1045. module_use_option:
  1046.     prefix_option
  1047.     |    import_option
  1048.     |    exclude_option
  1049.     |    rename_option
  1050.     |    export_option
  1051. ;
  1052.  
  1053. prefix_option:
  1054.     PREFIX_OPTION STRING
  1055.     { $$ = make_prefix_option($2); free($1); }
  1056. ;
  1057.  
  1058. import_option:
  1059.     IMPORT_OPTION ALL
  1060.     { $$ = make_use_option(useopt_IMPORT_ALL); free($1); free($2); }
  1061.     |    IMPORT_OPTION LBRACE imports_opt RBRACE
  1062.     { $$ = (struct use_option *) $3; free($1); free($2); free($4); }
  1063. ;
  1064.  
  1065. imports_opt:
  1066.     /* empty */        { $$ = make_import_option(); }
  1067.     |    imports            { $$ = $1; }
  1068. ;
  1069.  
  1070. imports:
  1071.     SYMBOL
  1072.     { $$ = add_import(make_import_option(), $1, NULL); }
  1073.     |    SYMBOL ARROW SYMBOL
  1074.     { $$ = add_import(make_import_option(), $1, $3); free($2); }
  1075.     |    imports COMMA SYMBOL
  1076.     { $$ = add_import($1, $3, NULL); free($2); }
  1077.     |    imports COMMA SYMBOL ARROW SYMBOL    
  1078.     { $$ = add_import($1, $3, $5); free($2); free($4); }
  1079. ;
  1080.  
  1081. exclude_option:
  1082.     EXCLUDE_OPTION variable_name_set
  1083.     { $$ = make_exclude_option($2); free($1); }
  1084. ;
  1085.  
  1086. export_option:
  1087.     EXPORT_OPTION ALL
  1088.     { $$ = make_use_option(useopt_EXPORT_ALL); free($1); free($2); }
  1089.     |    EXPORT_OPTION variable_name_set
  1090.     { $$ = make_export_option($2); free($1); }
  1091. ;
  1092.  
  1093. rename_option:
  1094.     RENAME_OPTION LBRACE RBRACE
  1095.     { $$ = make_rename_option(make_renamings());
  1096.       free($1); free($2); free($3); }
  1097.     |    RENAME_OPTION LBRACE rename_specs RBRACE
  1098.     { $$ = make_rename_option($3); free($1); free($2); free($4); }
  1099. ;
  1100.  
  1101. rename_specs:
  1102.     SYMBOL ARROW SYMBOL
  1103.     { $$ = add_renaming(make_renamings(), $1, $3); free($2); }
  1104.     |    rename_specs COMMA SYMBOL ARROW SYMBOL
  1105.     { $$ = add_renaming($1, $3, $5); free($2); free($4); }
  1106. ;
  1107.  
  1108. variable_name_set:
  1109.     LBRACE RBRACE    { $$ = make_variable_names(); free($1); free($2); }
  1110.     |    LBRACE variable_names RBRACE
  1111.     { $$ = $2; free($1); free($3); }
  1112. ;
  1113.  
  1114. variable_names:
  1115.     SYMBOL        { $$ = add_variable_name(make_variable_names(), $1); }
  1116.     |    variable_names COMMA SYMBOL
  1117.     { $$ = add_variable_name($1, $3); free($2); }
  1118. ;
  1119.  
  1120. library_definition:
  1121.     SYMBOL library_clauses_opt END library_opt symbol_opt
  1122.     { if ($5) {
  1123.           if (strcasecmp((char *)$1->chars, (char *)$5->chars) != 0) {
  1124.           error($5->line, "mismatched name, ``%s'' isn't ``%s''",
  1125.             $5->chars, $1->chars);
  1126.           yacc_recover();
  1127.           }
  1128.           free($5);
  1129.       } 
  1130.       free($3);
  1131.       $$ = (struct constituent *) set_namespace_name($2, $1);
  1132.     }
  1133. ;
  1134.  
  1135. library_opt:
  1136.     /* empty */         { $$ = NULL; }
  1137.     |    LIBRARY            { free($1); $$ = NULL; }
  1138.  
  1139. library_clauses_opt:
  1140.     /* empty */        { $$ = make_define_library(); }
  1141.     |    library_clauses
  1142.     |    library_clauses SEMI    { $$ = $1; free($2); }
  1143. ;
  1144.  
  1145. library_clauses:
  1146.     use_clause
  1147.     { $$ = add_use_clause(make_define_library(), $1); }
  1148.     |    export_clause
  1149.     { $$ = add_exports(make_define_library(), $1); }
  1150.     |    library_clauses SEMI use_clause
  1151.     { $$ = add_use_clause($1, $3); free($2); }
  1152.     |    library_clauses SEMI export_clause
  1153.     { $$ = add_exports($1, $3); free($2); }
  1154. ;
  1155.  
  1156.  
  1157. block_opt:    { $$ = NULL; } | BLOCK { free($1); $$ = NULL; } ;
  1158. case_opt:    { $$ = NULL; } | CASE { free($1); $$ = NULL; } ;
  1159. if_opt:        { $$ = NULL; } | IF { free($1); $$ = NULL; } ;
  1160. for_opt:    { $$ = NULL; } | FOR { free($1); $$ = NULL; } ;
  1161. select_opt:    { $$ = NULL; } | SELECT { free($1); $$ = NULL; } ;
  1162. unless_opt:    { $$ = NULL; } | UNLESS { free($1); $$ = NULL; } ;
  1163. until_opt:    { $$ = NULL; } | UNTIL { free($1); $$ = NULL; } ;
  1164. while_opt:    { $$ = NULL; } | WHILE { free($1); $$ = NULL; } ;
  1165. class_opt:    { $$ = NULL; } | CLASS { free($1); $$ = NULL; } ;
  1166. method_opt:    { $$ = NULL; } | METHOD { free($1); $$ = NULL; } ;
  1167. semi_opt:    { $$ = NULL; } | SEMI { free($1); $$ = NULL; } ;
  1168. arrow_opt:    { $$ = NULL; } | ARROW { free($1); $$ = NULL; } ;
  1169.  
  1170. symbol_opt:    { $$ = NULL; } | SYMBOL { $$ = $1; } ;
  1171. by_part_opt:    { $$ = NULL; } | by_part { $$ = $1; } ;
  1172. else_part_opt:    { $$ = NULL; } | else_part { $$ = $1; } ;
  1173. final_part_opt:    { $$ = NULL; } | final_part { $$ = $1; } ;
  1174.  
  1175. %%
  1176.  
  1177. static void yyerror(char *msg)
  1178. {
  1179.     if (yylval.token)
  1180.     error(yylval.token->line, "%s at or before `%s'\n",
  1181.           msg, yylval.token->chars);
  1182.     else
  1183.     error(line_count, "%s at end-of-file\n", msg);
  1184.     yacc_recover();
  1185. }
  1186.  
  1187. static boolean verify_symbol_aux(struct id *id, struct token *token)
  1188. {
  1189.     if (token) {
  1190.     int line = token->line;
  1191.     char *ptr = (char *)token->chars;
  1192.  
  1193.     if (*ptr == '\\')
  1194.         ptr++;
  1195.  
  1196.     if (strcasecmp((char *)id->symbol->name, ptr)) {
  1197.         error(line, "mismatched name, ``%s'' isn't ``%s''",
  1198.           token->chars, id->symbol->name);
  1199.         free(token);
  1200.         return TRUE;
  1201.     }
  1202.     else
  1203.         free(token);
  1204.     }
  1205.     return FALSE;
  1206. }
  1207.  
  1208. static void yacc_recover()
  1209. {
  1210.     while (yychar) {
  1211.     struct token_list *rlist = yacc_recovery_list;
  1212.     while (rlist)
  1213.         if (rlist->token == yychar)
  1214.         return;
  1215.         else
  1216.         rlist = rlist->next;
  1217.     yychar = yylex();
  1218.     }
  1219.     yyclearin;
  1220. }
  1221.  
  1222. static void push_yacc_recovery(int token)
  1223. {
  1224.     struct token_list *newrec;
  1225.  
  1226.     newrec = malloc(sizeof(*newrec));
  1227.     newrec->token = token;
  1228.     newrec->next = yacc_recovery_list;
  1229.     yacc_recovery_list = newrec;
  1230. }
  1231.  
  1232. static void pop_yacc_recoveries(int count)
  1233. {
  1234.     for ( ; count-- > 0; )
  1235.     yacc_recovery_list = yacc_recovery_list->next;
  1236. }
  1237.  
  1238. struct token *make_token(char *ptr, int len)
  1239. {
  1240.     struct token *token = malloc(sizeof(struct token) 
  1241.                  + len + 1 - sizeof(token->chars));
  1242.  
  1243.     token->length = len;
  1244.     memcpy(token->chars, ptr, len);
  1245.     token->line = line_count;
  1246.     token->chars[len] = 0;
  1247.  
  1248.     return token;
  1249. }
  1250.  
  1251.